home *** CD-ROM | disk | FTP | other *** search
/ Multimedia Producer's Bible / Multimedia Producer's Bible.iso / mac / mTropolis / mTropolis Sampler Files / mFactory Object Model Examples / Source / Momentum / Momentum.c next >
Encoding:
C/C++ Source or Header  |  1996-01-04  |  11.6 KB  |  396 lines  |  [TEXT/MMCC]

  1. /*    Momentum.c
  2. **
  3. **    Copyright 1995, mFactory, Inc.
  4. **    All rights reserved.
  5. */
  6.  
  7. #include "Momentum.h"
  8.  
  9. #define kActivatePopup         6                                                // DITL indices
  10. #define kTerminatePopup        8
  11. #define kMassField            17
  12. #define kAngleField            13
  13. #define kMagnitudeField        15
  14. #define kTermVelField        19
  15.  
  16. #define kGravServID            ((CompID *) "Gravity\0\0\0\0\0\0\0\0\0")        // service MOM ID
  17.  
  18. #define massAttrib            ((CompID *) "mass\0\0\0\0\0\0\0\0\0\0\0\0")        // attributes
  19. #define angleAttrib            ((CompID *) "initialangle\0\0\0\0")
  20. #define magnitudeAttrib        ((CompID *) "initialmagnitude")
  21. #define resVectorAttrib        ((CompID *) "resultantvector\0")
  22.  
  23. #define kTimePeriod            1                                                // milliseconds
  24.  
  25. static double pi            = 3.14159;
  26.  
  27.  
  28. /*    Initial entry point
  29. */
  30.  
  31. MCompMainFuncDcl MCompMainName(MInitInfo *initInfo)
  32. {
  33.     MDefineComponent(MomentumComp, kMCanDragOff);
  34.     MInheritClass(MComponent, kMCompNumProcs, kMBaseCompSlot);
  35.     
  36.     // MComponent methods we must override
  37.  
  38.     MDefineMethod(kMomentumSlot, kMBaseCompSlot, kMCompConstructor, MCompConstructor);
  39.     MDefineMethod(kMomentumSlot, kMBaseCompSlot, kMCompCopy, MCompCopy);
  40.     MDefineMethod(kMomentumSlot, kMBaseCompSlot, kMCompCopyConstructor, MCompCopyConstructor);
  41.     MDefineMethod(kMomentumSlot, kMBaseCompSlot, kMCompDestructor, MCompDestructor);
  42.  
  43.     // MComponent methods we choose to override
  44.  
  45.     MDefineMethod(kMomentumSlot, kMBaseCompSlot, kMCompEditorOpen, MCompEditorOpen);
  46.     MDefineMethod(kMomentumSlot, kMBaseCompSlot, kMCompEditorAccept, MCompEditorAccept);
  47.  
  48.     MDefineMethod(kMomentumSlot, kMBaseCompSlot, kMCompGetSaveInfo, MCompGetSaveInfo);
  49.     MDefineMethod(kMomentumSlot, kMBaseCompSlot, kMCompSaveComponent, MCompSaveComponent);
  50.     MDefineMethod(kMomentumSlot, kMBaseCompSlot, kMCompRestoreComponent, MCompRestoreComponent);
  51.  
  52.     MDefineMethod(kMomentumSlot, kMBaseCompSlot, kMCompProcessMessage, MCompProcessMessage);
  53.  
  54.     MDefineMethod(kMomentumSlot, kMBaseCompSlot, kMCompGetAttribute, MCompGetAttribute);
  55.     MDefineMethod(kMomentumSlot, kMBaseCompSlot, kMCompSetAttribute, MCompSetAttribute);
  56.  
  57.     MDefineMethod(kMomentumSlot, kMBaseCompSlot, kMCompAdaptIDs, MCompAdaptIDs);
  58.  
  59.     // Define our own methods
  60.  
  61.     MDefineMethod(kMomentumSlot, kMomentumSlot, kMomentumTask, MomentumTask);
  62.  
  63.     MConnectCommonServices(initInfo);
  64.     
  65.     MEndComponentDef;
  66. }
  67.  
  68.  
  69. /*    Initialize component
  70. */
  71.  
  72. static MErr MCompConstructor(MomentumComp *self, MObjectRef *mRef)
  73. {
  74.     MInitEvent(self->f_activateEvent, kMParentEnabled, 0);
  75.     MInitEvent(self->f_terminateEvent, kMNone, 0);
  76.     MInitDouble(self->f_mass, 5000.0);
  77.     MInitDouble(self->f_initialAngle, 0.0);
  78.     MInitDouble(self->f_initialMagnitude, 0.0);
  79.     MInitDouble(self->f_terminalVelocity, 10.0);
  80.     return kMNoCompErr;
  81. }
  82.  
  83.  
  84. /*    Copy component data
  85. */
  86.  
  87. static MErr MCompCopy(MomentumComp *self, MomentumComp *previousSelf)
  88. {
  89.     MCopyEvent(self->f_activateEvent, previousSelf->f_activateEvent);
  90.     MCopyEvent(self->f_terminateEvent, previousSelf->f_terminateEvent);
  91.     MCopyDouble(self->f_mass, previousSelf->f_mass);
  92.     MCopyDouble(self->f_initialAngle, previousSelf->f_initialAngle);
  93.     MCopyDouble(self->f_initialMagnitude, previousSelf->f_initialMagnitude);
  94.     MCopyDouble(self->f_terminalVelocity, previousSelf->f_terminalVelocity);
  95.     return kMNoCompErr;
  96. }
  97.  
  98.  
  99. /*    Copy component
  100. */
  101.  
  102. static MErr MCompCopyConstructor(MomentumComp *self, MomentumComp *previousSelf, MObjectRef *mRef)
  103. {
  104.     MCompConstructor(self, mRef);
  105.     return MCompCopy(self, previousSelf);
  106. }
  107.  
  108.  
  109. /*    Dispose component
  110. */
  111.  
  112. static MErr MCompDestructor(MomentumComp *self)
  113. {
  114.     MDisposeEvent(self->f_activateEvent);
  115.     MDisposeEvent(self->f_terminateEvent);
  116.     MDisposeDouble(self->f_mass);
  117.     MDisposeDouble(self->f_initialAngle);
  118.     MDisposeDouble(self->f_initialMagnitude);
  119.     MDisposeDouble(self->f_terminalVelocity);
  120.     return kMNoCompErr;
  121. }
  122.  
  123.  
  124. /*    Open component dialog
  125. */
  126.  
  127. static MErr MCompEditorOpen(MomentumComp *self, void *editor, short editorType)
  128. {
  129.     if ( editorType == kMDialogEditorType ) {
  130.         MSetEditorItem(editor, kActivatePopup, (MDataType *) &self->f_activateEvent);
  131.         MSetEditorItem(editor, kTerminatePopup, (MDataType *) &self->f_terminateEvent);
  132.         MSetEditorItem(editor, kMassField, (MDataType *) &self->f_mass);
  133.         MSetEditorItem(editor, kAngleField, (MDataType *) &self->f_initialAngle);
  134.         MSetEditorItem(editor, kMagnitudeField, (MDataType *) &self->f_initialMagnitude);
  135.         MSetEditorItem(editor, kTermVelField, (MDataType *) &self->f_terminalVelocity);
  136.         return kMNoCompErr;
  137.     } else
  138.         return kMUnableToComplyCompErr;
  139. }
  140.  
  141.  
  142. /*    Close component dialog
  143. */
  144.  
  145. static MErr MCompEditorAccept(MomentumComp *self, void *editor)
  146. {
  147.     MGetEditorItem(editor, kActivatePopup, (MDataType *) &self->f_activateEvent);
  148.     MGetEditorItem(editor, kTerminatePopup, (MDataType *) &self->f_terminateEvent);
  149.     MGetEditorItem(editor, kMassField, (MDataType *) &self->f_mass);
  150.     MGetEditorItem(editor, kAngleField, (MDataType *) &self->f_initialAngle);
  151.     MGetEditorItem(editor, kMagnitudeField, (MDataType *) &self->f_initialMagnitude);
  152.     MGetEditorItem(editor, kTermVelField, (MDataType *) &self->f_terminalVelocity);
  153.     return kMNoCompErr;
  154. }
  155.  
  156.  
  157. /*    Provide save information
  158. */
  159.  
  160. static MErr MCompGetSaveInfo(MomentumComp *self, MFileIOServ *file, long saveInfo, short *rev, long *len)
  161. {
  162.     long    valueSize;
  163.  
  164.     MSizeOfValue(file, &self->f_activateEvent, &valueSize);
  165.     *len = valueSize;
  166.     MSizeOfValue(file, &self->f_terminateEvent, &valueSize);
  167.     *len += valueSize;
  168.     MSizeOfValue(file, &self->f_mass, &valueSize);
  169.     *len += valueSize;
  170.     MSizeOfValue(file, &self->f_initialAngle, &valueSize);
  171.     *len += valueSize;
  172.     MSizeOfValue(file, &self->f_initialMagnitude, &valueSize);
  173.     *len += valueSize;
  174.     MSizeOfValue(file, &self->f_terminalVelocity, &valueSize);
  175.     *len += valueSize;
  176.  
  177.     *rev = kMomentumRev;
  178.     return kMNoCompErr;
  179. }
  180.  
  181.  
  182. /*    Save component
  183. */
  184.  
  185. static MErr MCompSaveComponent(MomentumComp *self, MFileIOServ *file, long saveInfo)
  186. {
  187.     MWriteValue(file, &self->f_activateEvent);
  188.     MWriteValue(file, &self->f_terminateEvent);
  189.     MWriteValue(file, &self->f_mass);
  190.     MWriteValue(file, &self->f_initialAngle);
  191.     MWriteValue(file, &self->f_initialMagnitude);
  192.     MWriteValue(file, &self->f_terminalVelocity);
  193.     
  194.     return kMNoCompErr;
  195. }
  196.  
  197.  
  198. /*    Restore component
  199. */
  200.  
  201. static MErr MCompRestoreComponent(MomentumComp *self, MFileIOServ *file, long saveInfo, short rev)
  202. {
  203.     if ( rev == kMomentumRev ) {
  204.         MReadValue(file, &self->f_activateEvent);
  205.         MReadValue(file, &self->f_terminateEvent);
  206.         MReadValue(file, &self->f_mass);
  207.         MReadValue(file, &self->f_initialAngle);
  208.         MReadValue(file, &self->f_initialMagnitude);
  209.         MReadValue(file, &self->f_terminalVelocity);
  210.         return kMNoCompErr;
  211.     }
  212.     else
  213.         return kMUnableToComplyCompErr;
  214. }
  215.  
  216.  
  217. /*    Process incoming message
  218. */
  219.  
  220. static MErr MCompProcessMessage(MomentumComp *self, MMessagePtr message)
  221. {
  222.     if ( MDetectMessage(message, self->f_activateEvent) ) {
  223.         MService    *gravServ;
  224.  
  225.         MGetService(self, kGravServID, kMAnyInstance, kMSpawnIfNotFound, &gravServ);
  226.         if ( MError() == kMNoCompErr ) {
  227.             long        globalTime;
  228.             double        radians, cosVal, sinVal;
  229.                         
  230.             MAddClient(gravServ, self);
  231.             MPostCTimeTask(self, nil, kTimePeriod, kMomentumSlot, kMomentumTask);
  232.  
  233.             MGetGlobalTime(&globalTime);
  234.             self->f_timeStamp = globalTime;
  235.             self->f_accelerationX = self->f_accelerationY = 0.0;
  236.             
  237.             self->f_fractionalX = 0.0;
  238.             self->f_fractionalY = 0.0;
  239.             
  240.             radians = self->f_initialAngle.f_value * pi / 180.0;
  241.             MCos(&cosVal, radians);
  242.             MSin(&sinVal, radians);
  243.             self->f_velocityX = self->f_initialMagnitude.f_value * cosVal;    
  244.             self->f_velocityY = -(self->f_initialMagnitude.f_value * sinVal);        
  245.         }
  246.         return kMNoCompErr;
  247.     }
  248.     else if ( MDetectMessage(message, self->f_terminateEvent) || MDetectDisableMessage(message) ) {
  249.         MService    *gravServ;
  250.         
  251.         MGetService(self, kGravServID, kMAnyInstance, kMSpawnIfNotFound, &gravServ);
  252.         if ( MError() == kMNoCompErr ) 
  253.             MDeleteClient(gravServ, self);
  254.         MKillCTimeTask(self, nil);
  255.         return kMNoCompErr;
  256.     }
  257.     else
  258.         return kMUnableToComplyCompErr;
  259. }
  260.  
  261.  
  262. /*    Get component attribute
  263. */
  264.  
  265. static MErr MCompGetAttribute(MomentumComp *self, MomID attribName, MDataType *selector, MDataType *dataValue)
  266. {
  267.     if ( MCmpMomID(attribName, kMPositionAttrib) ) {
  268.         MObjectRef    *element;
  269.         MPoint2D    position;
  270.  
  271.         MGetElement(&element);
  272.         MGetElementAttribute(element, kMPositionAttrib, NULL, dataValue);
  273.  
  274.         MInitPoint2D(position, dataValue->f_point.f_value.PNTX, dataValue->f_point.f_value.PNTY);
  275.         MInitVector2D(dataValue->f_vector, position.f_value.PNTX + self->f_fractionalX, position.f_value.PNTY + self->f_fractionalY);
  276.         return kMNoCompErr;
  277.     }
  278.     else if ( MCmpMomID(attribName, kMSizeAttrib) ) {
  279.         MObjectRef    *element;
  280.  
  281.         MGetElement(&element);
  282.         MGetElementAttribute(element, kMSizeAttrib, NULL, dataValue);
  283.         return kMNoCompErr;
  284.     }
  285.     else if ( MCmpMomID(attribName, massAttrib) ) {
  286.         dataValue->f_double = self->f_mass;
  287.         return kMNoCompErr;
  288.     }
  289.     else if ( MCmpMomID(attribName, kMEventsAttrib) && selector &&
  290.                  selector->f_type.f_type == kMInteger ) {
  291.         switch (selector->f_integer.f_value & ~kMEventMask) {
  292.             case kMEventExecute:
  293.                 if ( (selector->f_integer.f_value & kMEventMask) == 1 ) {
  294.                     MCopyEvent(dataValue->f_event, self->f_activateEvent);
  295.                     return kMNoCompErr;
  296.                 }
  297.                 else
  298.                     return kMUnableToComplyCompErr;
  299.  
  300.             case kMEventTerminate:
  301.                 if ( (selector->f_integer.f_value & kMEventMask) == 1 ) {
  302.                     MCopyEvent(dataValue->f_event, self->f_terminateEvent);
  303.                     return kMNoCompErr;
  304.                 }
  305.                 else
  306.                     return kMUnableToComplyCompErr;
  307.  
  308.             default:
  309.                 return kMUnableToComplyCompErr;
  310.         }
  311.     } 
  312.     else
  313.         return kMUnableToComplyCompErr;
  314. }
  315.  
  316.  
  317. /*    Set component attribute
  318. */
  319.  
  320. static MErr MCompSetAttribute(MomentumComp *self, MomID attribName,  MDataType *selector, MDataType *dataValue)
  321. {
  322.     if ( MCmpMomID(attribName, (CompID *) resVectorAttrib) ) {
  323.         self->f_accelerationX = dataValue->f_vector.f_angle;
  324.         self->f_accelerationY = dataValue->f_vector.f_magnitude;
  325.         return kMNoCompErr;
  326.     }  
  327.     else
  328.         return kMUnableToComplyCompErr;
  329. }
  330.  
  331.  
  332. /*    Adjust project-specific IDs
  333. */
  334.  
  335. static MErr MCompAdaptIDs(MomentumComp *self, MObjectPtr *sourceStore, MObjectPtr *targetStore)
  336. {
  337.     MTranslateID(kMTranslateEventID, sourceStore, targetStore, (MDataType *) &self->f_activateEvent);
  338.     MTranslateID(kMTranslateEventID, sourceStore, targetStore, (MDataType *) &self->f_terminateEvent);
  339.     return kMNoCompErr;
  340. }
  341.  
  342.  
  343. /*    Momentum task
  344. */
  345.  
  346. static MErr MomentumTask(MomentumComp *self, MTInfo *tinfo)
  347. {
  348.     double    deltaVelocityX, deltaVelocityY;
  349.     double    signX, signY;
  350.     double    tmpX, tmpY;
  351.     double    absVal;
  352.     long    globalTime, deltaTime;
  353.  
  354.     MGetGlobalTime(&globalTime);
  355.     deltaTime = globalTime - self->f_timeStamp;
  356.  
  357.     deltaVelocityX = (double) deltaTime * self->f_accelerationX / (double) kMGlobalTimeConst;
  358.     deltaVelocityY = (double) deltaTime * self->f_accelerationY / (double) kMGlobalTimeConst;
  359.  
  360.     tmpX = self->f_velocityX + deltaVelocityX;
  361.     tmpY = self->f_velocityY + deltaVelocityY;
  362.     signX = tmpX < 0.0 ? -1.0 : 1.0;
  363.     signY = tmpY < 0.0 ? -1.0 : 1.0;
  364.  
  365.     MFabs(&absVal, tmpX);
  366.     self->f_velocityX = absVal > self->f_terminalVelocity.f_value ?
  367.             self->f_terminalVelocity.f_value * signX : tmpX;
  368.     MFabs(&absVal, tmpY);
  369.     self->f_velocityY = absVal > self->f_terminalVelocity.f_value ?
  370.             self->f_terminalVelocity.f_value * signY : tmpY;
  371.  
  372.     if ( self->f_velocityX || self->f_velocityY ) {
  373.         MDataType    curPos;
  374.         double        dPosX, dPosY;
  375.         MObjectRef    *element;
  376.  
  377.         MInitPoint2D(curPos.f_point, 0, 0);
  378.         MGetElement(&element);
  379.         MGetElementAttribute(element, kMPositionAttrib, NULL, &curPos);
  380.  
  381.         dPosX = (double) curPos.f_point.f_value.PNTX + self->f_fractionalX;
  382.         dPosY = (double) curPos.f_point.f_value.PNTY + self->f_fractionalY;
  383.  
  384.         curPos.f_point.f_value.PNTX = dPosX + self->f_velocityX;
  385.         curPos.f_point.f_value.PNTY = dPosY + self->f_velocityY;
  386.  
  387.         self->f_fractionalX = dPosX + self->f_velocityX - curPos.f_point.f_value.PNTX;
  388.         self->f_fractionalY = dPosY + self->f_velocityY - curPos.f_point.f_value.PNTY;
  389.  
  390.         MSetElementAttribute(element, kMPositionAttrib, NULL, &curPos);
  391.     }
  392.  
  393.     self->f_timeStamp = globalTime;
  394.     return kMNoCompErr;
  395. }
  396.